package com.wr.recruit.service.service.impl;

import com.wr.recruit.service.dao.dbo.CompanyDbo;
import com.wr.recruit.service.dao.dbo.RoleDbo;
import com.wr.recruit.service.dao.dbo.UserDbo;
import com.wr.recruit.service.dao.repo.CompanyRepo;
import com.wr.recruit.service.dao.repo.RoleRepo;
import com.wr.recruit.service.dao.repo.UserRepo;
import com.wr.recruit.service.service.UserService;
import com.wr.recruit.service.utils.MD5Util;
import org.apache.tomcat.util.security.MD5Encoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import sun.security.provider.MD5;

import javax.annotation.PostConstruct;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Objects;

import static com.wr.recruit.service.utils.Constants.*;

@Service
public class UserServiceImpl implements UserService {

    private UserRepo userRepo;
    private RoleRepo roleRepo;
    private CompanyRepo companyRepo;

    @Autowired
    public UserServiceImpl(UserRepo userRepo,
                           RoleRepo roleRepo,
                           CompanyRepo companyRepo) {
        this.userRepo = userRepo;
        this.roleRepo = roleRepo;
        this.companyRepo = companyRepo;
    }

    @Override
    public UserDbo getUserInfo(String userName) {
        return userRepo.findAllByUserName(userName);
    }

    @Override
    public UserDbo updateUserInfo(UserDbo user) {
        UserDbo allById = userRepo.findAllByUserName(user.getUserName());
        if (!Objects.isNull(allById)){
            if (!Objects.isNull(user.getPassword()))
                allById.setPassword(generatePassword(user.getUserName(), user.getPassword()));
            if (!Objects.isNull(user.getTrueName()))
                allById.setTrueName(user.getTrueName());
            if (!Objects.isNull(user.getPhone()))
                allById.setPhone(user.getPhone());
            if (!Objects.isNull(user.getMail()))
                allById.setMail(user.getMail());
            if(!Objects.isNull(user.getStatus()))
                allById.setStatus(user.getStatus());
            return userRepo.save(allById);
        }
        return null;
    }

    @Override
    public UserDbo updateUserPassword(String userName, String password) {
        UserDbo allById = userRepo.findAllByUserName(userName);
        if (!Objects.isNull(allById)){
            RoleDbo roleInfo = roleRepo.findAllByRoleCode(INVESTIGATOR);
            if (ADMIN.equals(roleInfo.getRoleName())){
                String newPassoword = generatePassword(userName, password);
                allById.setPassword(newPassoword);
                return userRepo.save(allById);
            }
        }
        return null;
    }

    @Override
    public UserDbo grantUserRole(Integer userId, Integer grantUserId, int roleId) {
        UserDbo allById = userRepo.findAllById(userId);
        if (!Objects.isNull(allById)){
            RoleDbo roleInfo = roleRepo.findAllById(allById.getRoleId());
            //admin用户最大权限
            if (ADMIN.equals(roleInfo.getRoleName())){
                UserDbo grantUser = userRepo.findAllById(grantUserId);
                if (!Objects.isNull(grantUser)){
                    grantUser.setRoleId(roleId);
                    return userRepo.save(allById);
                }
            } else if (INVESTIGATOR.equals(roleInfo.getRoleName())){
                UserDbo grantUser = userRepo.findAllById(grantUserId);
                //同公司赋予角色
                if (allById.getCompanyCode().equals(grantUser.getCompanyCode())){
                    grantUser.setRoleId(roleId);
                    return userRepo.save(allById);
                }
                //录用并赋予角色
                if (Objects.isNull(grantUser.getCompanyCode())){
                    grantUser.setCompanyCode(allById.getCompanyCode());
                    grantUser.setRoleId(roleId);
                    return userRepo.save(allById);
                }
            }
        }
        return null;
    }

    @PostConstruct
    private void initUserInfo() {
        UserDbo allByUserName = userRepo.findAllByUserName(ADMIN);
        if (Objects.isNull(allByUserName)){
            Timestamp timestamp = new Timestamp(new Date().getTime());
            UserDbo userDbo = new UserDbo(ADMIN,generatePassword(ADMIN,ADMIN),ADMIN,null,null,
                    1,null,false,false,null,timestamp,timestamp);
            userRepo.save(userDbo);
        }
    }

    @Override
    public UserDbo createUserInfo(UserDbo user) {
        UserDbo allByUserName = userRepo.findAllByUserName(user.getUserName());
        if (Objects.isNull(allByUserName)){
            if (Objects.isNull(user.getCompanyCode())){
                RoleDbo allByRoleName = roleRepo.findAllByRoleCode(APPLICANT);
                user.setRoleId(allByRoleName.getId());
                user.setStatus(false);

            } else {
                CompanyDbo allByCompanyCode = companyRepo.findAllByCompanyCode(user.getCompanyCode());
                if (Objects.isNull(allByCompanyCode)){
                    return null;
                }
                RoleDbo allByRoleCode = roleRepo.findAllByRoleCode(INVESTIGATOR);
                //此时公司新建 无hr角色用户
                if (userRepo.countAllByCompanyCodeAndRoleId(user.getCompanyCode(),allByRoleCode.getId()) <= 0)
                    user.setRoleId(allByRoleCode.getId());
                user.setRoleId(5);
                user.setStatus(true);
            }
            String newPassword = generatePassword(user.getUserName(), user.getPassword());
            user.setPassword(newPassword);
            user.setRevoked(false);
            user.setCreatedAt(new Timestamp(new Date().getTime()));
            user.setUpdatedAt(new Timestamp(new Date().getTime()));
            return userRepo.save(user);
        }
        return null;
    }

    @Override
    public void revokeUserInfo(Integer userId) {
        UserDbo allById = userRepo.findAllById(userId);
        allById.setRevoked(true);
        userRepo.save(allById);
    }

    @Override
    public Page<UserDbo> getAllUserList(int pageSize, int pageNum) {
        Specification<UserDbo> specification = new Specification<UserDbo>() {
            @Override
            public Predicate toPredicate(Root<UserDbo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate p1 = cb.equal(root.get("isRevoked").as(Boolean.class),false);
                query.where(p1);
                return query.getRestriction();
            }
        };
        return userRepo.findAll(specification, new PageRequest(pageNum - 1, pageSize));
    }

    @Override
    public Page<UserDbo> getUserListByUserName(String value, int pageSize, int pageNum) {
        Specification<UserDbo> specification = new Specification<UserDbo>() {
            @Override
            public Predicate toPredicate(Root<UserDbo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate p1 = cb.equal(root.get("isRevoked").as(Boolean.class),false);
                Predicate p2 = cb.like(root.get("userName").as(String.class), "%"+value+"%");
                query.where(cb.and(p1,p2));
                return query.getRestriction();
            }
        };
        return userRepo.findAll(specification,new PageRequest(pageNum - 1, pageSize));
    }

    private String generatePassword(String userName, String password){
        String key = userName + password;
        return MD5Util.MD5(key);
    }
}
